#include "plate_solver.h"

#include "im2d.h"
#include "rga.h"
#include "rkmedia_buffer.h"

#include "dwarf_utils.h"
#include "elog.h"
#include "elog_file.h"

using namespace cv;
using namespace std;
using Clock = std::chrono::system_clock;
namespace fs = std::filesystem;

int PlateSolver::start(EquatorialCoordinates& eqCoord, HourAngleCoordinates& haCoord) {
    Clock::time_point now = Clock::now();
    MEDIA_BUFFER img_mb = cam_tele_.getRgbMB_4k(1920, 1080);
    if (img_mb == NULL)
        return -1;

    Mat img = Mat(1080, 1920, CV_8UC3, (unsigned char*)RK_MPI_MB_GetPtr(img_mb));

    int ret = play_solving_->start(img, eqCoord);

    haCoordAtTime(eqCoord, now, haCoord);

    rkfree(img_mb);
    
    return ret;
}

int PlateSolver::stop() {
    play_solving_->stop();
    
    return 0;
}

void PlateSolver::haCoordAtTime(const EquatorialCoordinates& starEqCoordJ2000, const Clock::time_point& time_point, HourAngleCoordinates& starHaCoord) {
    time_t t = Clock::to_time_t(time_point);
    tm utc_time;
    gmtime_r(&t, &utc_time);

    auto msec = std::chrono::duration_cast<std::chrono::milliseconds>(time_point.time_since_epoch()).count() % 1000;
    double sec = utc_time.tm_sec + static_cast<double>(msec) / 1000.0;

    EquatorialCoordinates starEqCoordJNow = Ephemeris::equatorialEquinoxToEquatorialJNowAtDateAndTime(starEqCoordJ2000, 2000, 
                                                                                utc_time.tm_mday, utc_time.tm_mon + 1, utc_time.tm_year + 1900, 
                                                                                utc_time.tm_hour, utc_time.tm_min, sec);

    starHaCoord = Ephemeris::equatorialToHACoordinatesAtDateAndTime(starEqCoordJNow,
                                                                    utc_time.tm_mday, utc_time.tm_mon + 1, utc_time.tm_year + 1900, 
                                                                    utc_time.tm_hour, utc_time.tm_min, sec);
}

int AstrometryNet::start(const cv::Mat& img, EquatorialCoordinates& eqCoord) {
    string fits_name = to_string(try_times_) + string(".fits");
    fs::path fits_path = fits_parent_path_ / fits_name;

    fs::path xyfits_path(fits_path);
    xyfits_path.replace_extension(".xy.fits");

    fs::path xywcs_path(fits_path);
    xywcs_path.replace_extension(".xy.wcs");

    fs::path jpg_path(fits_path);
    jpg_path.replace_extension(".jpg");

#if !DEBUG_CALIBRATION
    file_manager_.convertToFits(img, fits_path.c_str());
    imwrite(jpg_path.string(), img);
#endif

    try_times_++;

    string cmd = "image2xy -O -d 3 ";
    cmd += fits_path.string();
	log_i("%s", cmd.c_str());

    char line[300] = {0};
    FILE* fp = popen(cmd.c_str(), "r");
	if (fp != NULL) {
        while (fgets(line, 300, fp) != NULL);
        pclose(fp);
    }

    if (!fs::exists(xyfits_path)) {
        log_i("image2xy failed");
        fs::remove(fits_path);
        return -1;
    }

    cmd = "solve-field --no-plots --no-remove-lines --uniformize 0 --overwrite --scale-units degwidth --scale-low 3.1 --scale-high 3.25 --sort-column FLUX --corr none --scamp-ref none --rdls none --match none --solved none --axy none --new-fits none --index-xyls none --no-plots ";
    cmd += xyfits_path.string();
    log_i("%s", cmd.c_str());

    fp = popen(cmd.c_str(), "r");
	if (fp != NULL) {
        while (fgets(line, 300, fp) != NULL) {
            if (strstr(line, "Field center: (RA,Dec)") != NULL) {
                log_i("solve success");

                sscanf(line, "Field center: (RA,Dec) = (%lf, %lf) deg.", &eqCoord.ra, &eqCoord.dec);
                eqCoord.ra /= 15.0;// 将度转化为小时                                                         
                log_i("result_ra is %lf, result_dec is %lf", eqCoord.ra, eqCoord.dec);
            }
        }
        pclose(fp);
    }

    if (!fs::exists(xywcs_path)) {
        log_i("solve-field failed");
        fs::remove(fits_path);
        fs::remove(xyfits_path);
        return -1;
    }

    fs::remove(fits_path);
    fs::remove(xyfits_path);
    fs::remove(xywcs_path);

    return 0;
}

int AstrometryNet::stop() {
    system("killall image2xy");
    system("killall astrometry-engine");
    system("killall solve-field");

    return 0;
}